// SpontLight 点光
// 照射所有方向的光源
import { 
  AmbientLight, 
  AxesHelper, 
  BoxGeometry, 
  CameraHelper, 
  Color, 
  Mesh, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial,
  PCFSoftShadowMap, 
  PerspectiveCamera, PlaneGeometry, PointLight, PointLightHelper, Scene, 
  SphereGeometry, 
  Vector3, 
  WebGLRenderer 
} from "three"
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls'
import Stats from 'stats.js'
import { GUI } from 'dat.gui'

const scene = new Scene()
const camera = new PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
// 设置相机位置
camera.position.set(-30, 40, 30)
camera.lookAt(new Vector3(0, 0, 0))

const renderer = new WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio)
renderer.shadowMap.enabled = true
renderer.shadowMap.type = PCFSoftShadowMap

renderer.setClearColor(0x000000)
renderer.setSize(window.innerWidth, window.innerHeight)

document.body.appendChild(renderer.domElement)

// 创建一个平面
const planeGeometry = new PlaneGeometry(70, 50)
const planeMaterial = new MeshPhongMaterial({ color: 0x9acd32 })
const plane = new Mesh(planeGeometry, planeMaterial)
// 接收阴影
plane.receiveShadow = true

plane.rotation.x = -0.5 * Math.PI
plane.position.set(15, 0, 0)
scene.add(plane)

const geometry = new BoxGeometry(4, 4, 4)
const material = new MeshLambertMaterial({ color: 0xff0000 })
const cube = new Mesh(geometry, material)

cube.position.set(-8, 2, 0)
// 正方体投射阴影
cube.castShadow = true

scene.add( cube )

// 添加坐标系，方便理解
const axes = new AxesHelper(15)
scene.add(axes)

// 添加环境光
let ambientColor = '#0c0c0c'
const ambientLight = new AmbientLight(ambientColor)
scene.add(ambientLight)

// 灯光设置
let pointColor = '#ccffcc'
let pointLight = new PointLight(pointColor)
// 强度
pointLight.decay = 0.1
pointLight.castShadow = true
// pointLight.position.set(29, 1, 20)
scene.add(pointLight)

let helper = new PointLightHelper(pointLight)
scene.add(helper)

let shadowHelper = new CameraHelper(pointLight.shadow.camera)
scene.add(shadowHelper)

let sphereLight = new SphereGeometry(0.2)
let sphereLightMaterial = new MeshBasicMaterial({color: 0xac6c25})
let sphereLightMesh = new Mesh(sphereLight, sphereLightMaterial)
sphereLightMesh.position.set(3, 0, 5)
scene.add(sphereLightMesh)

// 添加 FPS 监控
let stats: Stats = new Stats()
stats.showPanel(0)
document.body.appendChild(stats.dom)

const controls = setupControls()
// 引入轨迹球控制器，添加鼠标控制功能
const trackballControls = new TrackballControls(camera, renderer.domElement)

let invert = 1
let phase = 0

function render() {
  helper.update()
  shadowHelper.update()
  trackballControls.update()
  stats.update()

  pointLight.position.copy(sphereLightMesh.position)

  if (phase > 2 * Math.PI) {
    invert = invert * -1
    phase -= 2 * Math.PI
  } else {
    phase += controls.rotationSpeed
  }

  sphereLightMesh.position.z = +(25 * Math.sin(phase))
  sphereLightMesh.position.x = +(14 * Math.cos(phase))
  sphereLightMesh.position.y = 5

  if (invert < 0) {
    let pivot = 14
    sphereLightMesh.position.x = (invert * (sphereLightMesh.position.x - pivot)) + pivot
  }

  requestAnimationFrame(render)
  renderer.render(scene, camera)
}
render()

function setupControls() {
  // 控制器
  let controls = new function () {
    this.rotationSpeed = 0.01
    this.bouncingSpeed = 0.03
    this.ambientColor = ambientLight.color.getStyle()
    this.pointColor = pointLight.color.getStyle()
    this.intensity = 1
    this.distance = pointLight.distance
  }

  const gui = new GUI();
  // 颜色选择功能
  gui.addColor(controls, 'ambientColor')
    .onChange(e => {
      ambientLight.color = new Color(e)
    })

  gui.addColor(controls, 'pointColor')
    .onChange(e => {
      pointLight.color = new Color(e)
    })

  // 设置距离
  gui.add(controls, 'distance', 0, 100).onChange(e => {
    pointLight.distance = e
  })
  // 设置强度
  gui.add(controls, 'intensity', 0, 3).onChange(e=> {
    pointLight.intensity = e
  })
  // 速度控制
  gui.add(controls, 'rotationSpeed', 0, 0.01)

  return controls
}